package io.itit.ecp.admin.provide.action.controller.miniprogram;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import icu.mhb.mybatisplus.plugln.extend.Joins;
import io.itit.ecp.admin.common.constants.ParamConstants;
import io.itit.ecp.admin.common.enums.IDeviceEnums;
import io.itit.ecp.admin.common.enums.IMeterDeviceEnums;
import io.itit.ecp.admin.common.enums.MeterDeviceStaticsTypeEnums;
import io.itit.ecp.admin.common.enums.ProductTypeActiveStatus;
import io.itit.ecp.admin.provide.action.resp.CarbonEmissionDataActivityResp;
import io.itit.ecp.admin.provide.action.resp.largescreen.*;
import io.itit.ecp.admin.provide.action.resp.miniprogram.MiniDeviceInfoCategoryResp;
import io.itit.ecp.admin.server.entity.*;
import io.itit.ecp.admin.server.service.*;
import io.itit.grass.common.provide.action.resp.ResultResp;
import io.itit.grass.common.server.entity.BaseEntity;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * 小程序能源数据
 */
@Api(tags = "小程序能源数据")
@RestController
@RequestMapping("/mini/energy")
public class MiniEnergyController {

    @Resource
    private IEnergyDataService energyDataService;

    @Resource
    private IDeviceService deviceService;

    @Resource
    private IMeterDeviceService meterDeviceService;

    @Resource
    private IProductTypeService productTypeService;

    @Resource
    private ISceneProjectService sceneProjectService;

    @Resource
    private ISceneEdificeService sceneEdificeService;

    @Resource
    private ISceneFloorService sceneFloorService;

    @Resource
    private ISceneRoomService sceneRoomService;

    @Resource
    private IActivityCarbonEmissionService activityCarbonEmissionService;

    @Resource
    private IEnergyCategoryService energyCategoryService;

    @Resource
    private IEnergyConsumptionTypeService energyConsumptionTypeService;

    @Resource
    private IDataFillingDataService dataFillingDataService;

    /**
     * 查询能源总量
     */
    @GetMapping("total")
    @ApiOperation("查询能源总量")
    public ResultResp<Map<String, Object>> getTotal(@RequestParam(required = false) String sceneProjectId,
                                                    @RequestParam(required = false) String sceneEdificeId,
                                                    @RequestParam(required = false) String sceneFloorId,
                                                    @RequestParam(required = false) String startTime,
                                                    @RequestParam(required = false) String endTime) {
        LocalDateTime start = StringUtils.hasLength(startTime) ? LocalDate.parse(startTime, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atTime(LocalTime.MIN) : null;
        LocalDateTime end = StringUtils.hasLength(endTime) ? LocalDate.parse(endTime, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atTime(LocalTime.MAX) : LocalDateTime.now();
        EnergyDataEntity dataEntity = energyDataService.getOne(new QueryWrapper<EnergyDataEntity>()
                .select("SUM(standard_coal) AS standard_coal")
                .eq(StringUtils.hasLength(sceneProjectId), "scene_project_id", sceneProjectId)
                .eq(StringUtils.hasLength(sceneEdificeId), "scene_edifice_id", sceneEdificeId)
                .eq(StringUtils.hasLength(sceneFloorId), "scene_floor_id", sceneFloorId)
                .ge(Objects.nonNull(start), "solidify_date", start)
                .le("solidify_date", end));
        BigDecimal value = Objects.isNull(dataEntity) ? BigDecimal.ZERO : ObjectUtil.defaultIfNull(dataEntity.getStandardCoal(), BigDecimal.ZERO)
                .setScale(2, RoundingMode.HALF_DOWN);
        BigDecimal t = new BigDecimal("1000");
        Map<String, Object> result = new HashMap<>();
        String unit = "kgce";
        if (value.compareTo(t) >= 0) {
            value = value.divide(t, 2, RoundingMode.HALF_DOWN);
            unit = "tce";
        }
        result.put("value", value);
        result.put("unit", unit);
        return ResultResp.success(result);
    }


    @ApiOperation("设备数据统计")
    @GetMapping("deviceInfo")
    public ResultResp<MiniDeviceInfoCategoryResp> deviceInfo(@RequestParam(required = false) String sceneProjectId,
                                                             @RequestParam(required = false) String sceneEdificeId,
                                                             @RequestParam(required = false) String sceneFloorId,
                                                             @RequestParam(required = false) String startTime,
                                                             @RequestParam(required = false) String endTime) {
        LocalDateTime start = StringUtils.hasLength(startTime) ? LocalDate.parse(startTime, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atTime(LocalTime.MIN) : null;
        LocalDateTime end = StringUtils.hasLength(endTime) ? LocalDate.parse(endTime, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atTime(LocalTime.MAX) : LocalDateTime.now();
        MiniDeviceInfoCategoryResp resp = new MiniDeviceInfoCategoryResp();
        resp.setOnLineDevicesNum(deviceService.countOnline(sceneProjectId, sceneEdificeId, sceneFloorId) + meterDeviceService.countOnline(sceneProjectId, sceneEdificeId, sceneFloorId));
        resp.setOutLineDevicesNum(deviceService.countOffline(sceneProjectId, sceneEdificeId, sceneFloorId) + meterDeviceService.countOffline(sceneProjectId, sceneEdificeId, sceneFloorId));
        resp.setDevicesNum(resp.getOnLineDevicesNum() + resp.getOutLineDevicesNum());
        List<ProductTypeEntity> productTypeEntities = productTypeService.list(new LambdaQueryWrapper<ProductTypeEntity>()
                .eq(ProductTypeEntity::getActiveStatus, ProductTypeActiveStatus.ENABLED.getValue())
                .orderByAsc(ProductTypeEntity::getSort));
        Set<String> productTypeIds = productTypeEntities.stream().map(BaseEntity::getId).collect(Collectors.toSet());
        List<Map<String, Object>> devices = Collections.emptyList();
        List<MiniDeviceInfoCategoryResp.DeviceInfoCategory> deviceList = new ArrayList<>();
        if (!productTypeIds.isEmpty()) {
            devices = deviceByCategory(productTypeIds, sceneProjectId, sceneEdificeId, sceneFloorId);
        }
        for (ProductTypeEntity productTypeEntity : productTypeEntities) {
            MiniDeviceInfoCategoryResp.DeviceInfoCategory deviceInfoCategory = new MiniDeviceInfoCategoryResp.DeviceInfoCategory()
                    .setLabelName(productTypeEntity.getProductTypeName());
            deviceList.add(setDeviceInfoCategory(deviceInfoCategory, devices, productTypeEntity.getId()));
        }
        resp.setDevices(deviceList.stream().filter(item -> item.getOnLineDevicesNum() > 0 || item.getOutLineDevicesNum() > 0).collect(Collectors.toList()));

        List<MiniDeviceInfoCategoryResp.DeviceInfoCategory> meterDeviceList = new ArrayList<>();
        List<Map<String, Object>> listMaps = meterDevice(sceneProjectId, sceneEdificeId, sceneFloorId);
        for (ProductTypeEntity productTypeEntity : productTypeEntities) {
            Object onlineCount = listMaps.stream()
                    .filter(item -> Objects.equals(item.get("product_type_id"), productTypeEntity.getId()) && "1".equals(item.get("device_status")))
                    .map(item -> item.get("count_value"))
                    .findFirst()
                    .orElse(null);
            int online = Objects.isNull(onlineCount) ? 0 : Integer.parseInt(onlineCount.toString());
            Object offlineCount = listMaps.stream()
                    .filter(item -> Objects.equals(item.get("product_type_id"), productTypeEntity.getId()) && "2".equals(item.get("device_status")))
                    .map(item -> item.get("count_value"))
                    .findFirst()
                    .orElse(null);
            int offline = Objects.isNull(offlineCount) ? 0 : Integer.parseInt(offlineCount.toString());
            MiniDeviceInfoCategoryResp.DeviceInfoCategory deviceInfoCategory = new MiniDeviceInfoCategoryResp.DeviceInfoCategory()
                    .setLabelName(productTypeEntity.getProductTypeName())
                    .setOnLineDevicesNum(online)
                    .setOutLineDevicesNum(offline);
            if ("电表".equals(productTypeEntity.getProductTypeName())) { // 电表需要计算总功率
                // 电表总功率数据来源：
                //电表总功率=计量值/时间（15分钟的计量值*0.25，1小时的计量值*1）【现在数据的颗粒度为15分钟】
                //（1）电表设备的计量值数据来源：管理后台-数据管理-能源数据-计量值（此处计量为读表类型为“用电电表”并且统计类型为“用电量”的计量值）
                BigDecimal meterValue = energyDataService.getOneOpt(new QueryWrapper<EnergyDataEntity>()
                        .select("meter_value")
                        .eq(StringUtils.hasLength(sceneProjectId), "scene_project_id", sceneProjectId)
                        .eq(StringUtils.hasLength(sceneEdificeId), "scene_edifice_id", sceneEdificeId)
                        .eq(StringUtils.hasLength(sceneFloorId), "scene_floor_id", sceneFloorId)
                        .eq("read_meter_type", IMeterDeviceEnums.ReadMeterType.readMeterType13.readMeterType)
                        .eq("statics_type", MeterDeviceStaticsTypeEnums.POWER_CONSUMPTION.getValue())
                        .ge(Objects.nonNull(start), "solidify_date", start)
                        .le("solidify_date", end)
                        .last(ParamConstants.LIMIT_ONE)
                        .orderByDesc("solidify_date")).map(EnergyDataEntity::getMeterValue).orElse(BigDecimal.ZERO);

                deviceInfoCategory.setTotalPower(meterValue.multiply(new BigDecimal("0.25")).setScale(2, RoundingMode.HALF_DOWN));
            }
            meterDeviceList.add(deviceInfoCategory);
        }

        resp.setMeterDevices(meterDeviceList.stream().filter(item -> item.getOnLineDevicesNum() > 0 || item.getOutLineDevicesNum() > 0).collect(Collectors.toList()));
        ;
        return ResultResp.success(resp);
    }

    /**
     * 用能趋势
     *
     * @param sceneProjectId sceneProjectId
     * @param sceneEdificeId sceneEdificeId
     * @param sceneFloorId   sceneFloorId
     * @param startTime      startTime
     * @param endTime        endTime
     */
    @ApiOperation("用能趋势")
    @GetMapping("energyconsumptiontrend")
    public ResultResp<List<EnergyConsumptionTrendResp>> energyConsumptionTrend(@RequestParam(required = false) String sceneProjectId,
                                                                               @RequestParam(required = false) String sceneEdificeId,
                                                                               @RequestParam(required = false) String sceneFloorId,
                                                                               @RequestParam(required = false) String startTime,
                                                                               @RequestParam(required = false) String endTime) {
        LocalDateTime start = StringUtils.hasLength(startTime) ? LocalDate.parse(startTime, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atTime(LocalTime.MIN) : null;
        LocalDateTime end = StringUtils.hasLength(endTime) ? LocalDate.parse(endTime, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atTime(LocalTime.MAX) : LocalDateTime.now();
        String unit = "kgce";
        List<EnergyDataEntity> energyDataEntities = energyDataService.list(new QueryWrapper<EnergyDataEntity>()
                .select("solidify_date", "standard_coal")
                .eq(StringUtils.hasLength(sceneProjectId), "scene_project_id", sceneProjectId)
                .eq(StringUtils.hasLength(sceneEdificeId), "scene_edifice_id", sceneEdificeId)
                .eq(StringUtils.hasLength(sceneFloorId), "scene_floor_id", sceneFloorId)
                .ge(Objects.nonNull(start), "solidify_date", start)
                .le("solidify_date", end)
                .orderByAsc("solidify_date")
        );
        String dateFormat = "yyyy-MM-dd HH:00";
        Map<String, List<EnergyDataEntity>> groupBySolidifyDateMap = energyDataEntities.stream()
                .collect(Collectors.groupingBy(item -> DateUtil.format(item.getSolidifyDate(), dateFormat), TreeMap::new, Collectors.toList()));
        List<EnergyConsumptionTrendResp.DataItem> dataDetailList = new ArrayList<>();
        for (Map.Entry<String, List<EnergyDataEntity>> entry : groupBySolidifyDateMap.entrySet()) {
            dataDetailList.add(new EnergyConsumptionTrendResp.DataItem()
                    .setTime(entry.getKey())
                    .setValue(entry.getValue()
                            .stream()
                            .map(EnergyDataEntity::getStandardCoal)
                            .filter(Objects::nonNull)
                            .reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, RoundingMode.HALF_DOWN)));
        }
        BigDecimal t = new BigDecimal("1000");
        if (dataDetailList.stream().anyMatch(item -> item.getValue().compareTo(t) >= 0)) {
            unit = "tce";
            for (EnergyConsumptionTrendResp.DataItem dataItem : dataDetailList) {
                dataItem.setValue(dataItem.getValue().divide(t, 2, RoundingMode.HALF_DOWN));
            }
        }
        return ResultResp.success(Collections.singletonList(new EnergyConsumptionTrendResp()
                .setName("碳排放量")
                .setUnit(unit)
                .setData(dataDetailList)));
    }

    /**
     * 碳排放量趋势
     *
     * @param sceneProjectId sceneProjectId
     * @param sceneEdificeId sceneEdificeId
     * @param sceneFloorId   sceneFloorId
     * @param type           type 0：时；1：日
     * @param startTime      startTime
     * @param endTime        endTime
     */
    @ApiOperation("碳排放量趋势")
    @GetMapping("carbonEmissionsTrend")
    public ResultResp<List<CarbonEmissionsTrendResp>> carbonEmissionsTrend(@RequestParam(required = false) String sceneProjectId,
                                                                           @RequestParam(required = false) String sceneEdificeId,
                                                                           @RequestParam(required = false) String sceneFloorId,
                                                                           @RequestParam String type,
                                                                           @RequestParam(required = false) String startTime,
                                                                           @RequestParam(required = false) String endTime) {
        LocalDateTime start = StringUtils.hasLength(startTime) ? LocalDate.parse(startTime, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atTime(LocalTime.MIN) : null;
        LocalDateTime end = StringUtils.hasLength(endTime) ? LocalDate.parse(endTime, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atTime(LocalTime.MAX) : LocalDateTime.now();
        List<EnergyDataEntity> energyDataEntities = Joins.of(EnergyDataEntity.class)
                .select(EnergyDataEntity::getSolidifyDate, EnergyDataEntity::getCarbonEmission)
                .leftJoin(MeterDeviceEntity.class, MeterDeviceEntity::getId, EnergyDataEntity::getMeterDeviceId)
                .notIn(MeterDeviceEntity::getReadMeterType, IMeterDeviceEnums.ReadMeterType.getZeroCarbonList())
                .end()
                .eq(StringUtils.hasLength(sceneProjectId), EnergyDataEntity::getSceneProjectId, sceneProjectId)
                .eq(StringUtils.hasLength(sceneEdificeId), EnergyDataEntity::getSceneEdificeId, sceneEdificeId)
                .eq(StringUtils.hasLength(sceneFloorId), EnergyDataEntity::getSceneFloorId, sceneFloorId)
                .ge(Objects.nonNull(start), EnergyDataEntity::getSolidifyDate, start)
                .le(EnergyDataEntity::getSolidifyDate, end)
                .orderByAsc(EnergyDataEntity::getSolidifyDate)
                .joinList(EnergyDataEntity.class);
        List<CarbonEmissionsTrendResp> trends = new ArrayList<>();
        String dateFormat = "yyyy-MM-dd HH:00";
        if (StringUtils.pathEquals("1", type)) {
            dateFormat = "yyyy-MM-dd";
        }
        String finalFormat = dateFormat;
        Map<String, List<EnergyDataEntity>> groupBySolidifyDateMap = energyDataEntities.stream()
                .collect(Collectors.groupingBy(item -> DateUtil.format(item.getSolidifyDate(), finalFormat), TreeMap::new, Collectors.toList()));
        List<CarbonEmissionsTrendResp.DataDetail> dataDetailList = new ArrayList<>();
        for (Map.Entry<String, List<EnergyDataEntity>> entry : groupBySolidifyDateMap.entrySet()) {
            dataDetailList.add(new CarbonEmissionsTrendResp.DataDetail().setTime(entry.getKey())
                    .setValue(entry.getValue()
                            .stream()
                            .map(EnergyDataEntity::getCarbonEmission)
                            .filter(Objects::nonNull)
                            .reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, RoundingMode.HALF_DOWN)));
        }
        String unit = "kgCO2";
        BigDecimal t = new BigDecimal("1000");
        if (dataDetailList.stream().anyMatch(item -> item.getValue().compareTo(t) >= 0)) {
            unit = "tCO2";
            for (CarbonEmissionsTrendResp.DataDetail item : dataDetailList) {
                item.setValue(item.getValue().divide(t, 2, RoundingMode.HALF_DOWN));
            }
        }
        trends.add(new CarbonEmissionsTrendResp().setName("碳排放量").setUnit(unit).setData(dataDetailList));
        return ResultResp.success(trends);
    }


    /**
     * 活动碳排放统计
     *
     * @param sceneProjectId sceneProjectId
     * @param sceneEdificeId sceneEdificeId
     * @param sceneFloorId   sceneFloorId
     * @param startTime      startTime
     * @param endTime        endTime
     */
    @ApiOperation("活动碳排放统计")
    @GetMapping("activityCarbonEmissionsStatistics")
    public ResultResp<List<ActivityCarbonEmissionsStatisticsResp>> activityCarbonEmissionsStatistics(@RequestParam(required = false) String sceneProjectId,
                                                                                                     @RequestParam(required = false) String sceneEdificeId,
                                                                                                     @RequestParam(required = false) String sceneFloorId,
                                                                                                     @RequestParam(required = false) String startTime,
                                                                                                     @RequestParam(required = false) String endTime) {
        LocalDateTime start = StringUtils.hasLength(startTime) ? LocalDate.parse(startTime, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atTime(LocalTime.MIN) : null;
        LocalDateTime end = StringUtils.hasLength(endTime) ? LocalDate.parse(endTime, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atTime(LocalTime.MAX) : LocalDateTime.now();
        List<ActivityCarbonEmissionEntity> activityCarbonEmissionEntities = activityCarbonEmissionService.list(new LambdaQueryWrapper<ActivityCarbonEmissionEntity>()
                .orderByAsc(ActivityCarbonEmissionEntity::getActivityName));
        String unit = "kgCO2";
        BigDecimal t = new BigDecimal("1000");
        List<CarbonEmissionDataActivityResp> dataList = Joins.of(EnergyDataEntity.class)
                .select(EnergyDataEntity::getCarbonEmission)
                .innerJoin(ActivityCarbonEmissionDataEntity.class, ActivityCarbonEmissionDataEntity::getTargetId,
                        EnergyDataEntity::getMeterDeviceId)
                .selectAs(ActivityCarbonEmissionDataEntity::getActivityCarbonId, CarbonEmissionDataActivityResp::getActivityCarbonEmissionId)
                .end()
                .innerJoin(ActivityCarbonEmissionEntity.class, ActivityCarbonEmissionEntity::getId, ActivityCarbonEmissionDataEntity::getActivityCarbonId)
                .selectAs(ActivityCarbonEmissionEntity::getActivityName, CarbonEmissionDataActivityResp::getActivityCarbonEmissionName)
                .end()
                .eq(StringUtils.hasLength(sceneProjectId), EnergyDataEntity::getSceneProjectId, sceneProjectId)
                .eq(StringUtils.hasLength(sceneEdificeId), EnergyDataEntity::getSceneEdificeId, sceneEdificeId)
                .eq(StringUtils.hasLength(sceneFloorId), EnergyDataEntity::getSceneFloorId, sceneFloorId)
                .ge(Objects.nonNull(start), EnergyDataEntity::getSolidifyDate, start)
                .le(EnergyDataEntity::getSolidifyDate, end).joinList(CarbonEmissionDataActivityResp.class);

        Set<String> aceIds = dataList.stream()
                .map(CarbonEmissionDataActivityResp::getActivityCarbonEmissionId).collect(Collectors.toSet());
        List<ActivityCarbonEmissionEntity> filterEntities = activityCarbonEmissionEntities
                .stream()
                .filter(item -> aceIds.contains(item.getId())).collect(Collectors.toList());
        List<ActivityCarbonEmissionsStatisticsResp> statisticsResps = new ArrayList<>();
        for (ActivityCarbonEmissionEntity carbonEmissionEntity : filterEntities) {
            BigDecimal value = dataList.stream().filter(item -> StringUtils.pathEquals(carbonEmissionEntity.getId(), item.getActivityCarbonEmissionId()))
                    .map(CarbonEmissionDataActivityResp::getCarbonEmission)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add)
                    .setScale(2, RoundingMode.HALF_DOWN);
            statisticsResps.add(new ActivityCarbonEmissionsStatisticsResp()
                    .setName(carbonEmissionEntity.getActivityName())
                    .setUnit(unit)
                    .setValue(value));
        }
        if (statisticsResps.stream().anyMatch(item -> item.getValue().compareTo(t) >= 0)) {
            unit = "tCO2";
            for (ActivityCarbonEmissionsStatisticsResp item : statisticsResps) {
                item.setUnit(unit);
                item.setValue(item.getValue().divide(t, 2, RoundingMode.HALF_DOWN));
            }
        }
        return ResultResp.success(statisticsResps);
    }

    /**
     * 碳排放分类统计
     *
     * @param sceneProjectId sceneProjectId
     * @param sceneEdificeId sceneEdificeId
     * @param sceneFloorId   sceneFloorId
     * @param startTime      startTime
     * @param endTime        endTime
     */
    @ApiOperation("碳排放分类统计")
    @GetMapping("carbonEmissionsClassification")
    public ResultResp<List<CarbonEmissionsClassificationResp>> carbonEmissionsClassification(@RequestParam(required = false) String sceneProjectId,
                                                                                             @RequestParam(required = false) String sceneEdificeId,
                                                                                             @RequestParam(required = false) String sceneFloorId,
                                                                                             @RequestParam(required = false) String startTime,
                                                                                             @RequestParam(required = false) String endTime) {
        LocalDateTime start = StringUtils.hasLength(startTime) ? LocalDate.parse(startTime, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atTime(LocalTime.MIN) : null;
        LocalDateTime end = StringUtils.hasLength(endTime) ? LocalDate.parse(endTime, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atTime(LocalTime.MAX) : LocalDateTime.now();
        List<ProductTypeEntity> productTypeEntities = productTypeService.list(new LambdaQueryWrapper<ProductTypeEntity>()
                .eq(ProductTypeEntity::getActiveStatus, ProductTypeActiveStatus.ENABLED.getValue())
                .orderByAsc(ProductTypeEntity::getSort));
        String unit = "kgCO2";
        BigDecimal t = new BigDecimal("1000");
        List<EnergyDataEntity> energyDataEntities = Joins.of(EnergyDataEntity.class)
                .selectAs(consumer ->
                        consumer
                                .add("ecp_tt_energy_data.product_type_id", "productTypeId", false)
                                .add("ecp_tt_energy_data.scene_edifice_id", "sceneEdificeId", false)
                                .add("ecp_tt_energy_data.scene_floor_id", "sceneFloorId", false)
                                .add("ecp_tt_energy_data.scene_room_id", "sceneRoomId", false)
                                .add("SUM(carbon_emission)", "carbonEmission", false)
                )
                .leftJoin(MeterDeviceEntity.class, MeterDeviceEntity::getId, EnergyDataEntity::getMeterDeviceId)
                .notIn(MeterDeviceEntity::getReadMeterType, IMeterDeviceEnums.ReadMeterType.getZeroCarbonList())
                .end()
                .eq(StringUtils.hasLength(sceneProjectId), EnergyDataEntity::getSceneProjectId, sceneProjectId)
                .eq(StringUtils.hasLength(sceneEdificeId), EnergyDataEntity::getSceneEdificeId, sceneEdificeId)
                .eq(StringUtils.hasLength(sceneFloorId), EnergyDataEntity::getSceneFloorId, sceneFloorId)
                .isNotNull(EnergyDataEntity::getProductTypeId)
                .ge(Objects.nonNull(start), EnergyDataEntity::getSolidifyDate, start)
                .le(EnergyDataEntity::getSolidifyDate, end)
                .groupBy(Arrays.asList(EnergyDataEntity::getProductTypeId, EnergyDataEntity::getSceneEdificeId, EnergyDataEntity::getSceneFloorId, EnergyDataEntity::getSceneRoomId))
                .joinList(EnergyDataEntity.class);
        List<CarbonEmissionsClassificationResp> classificationResps = new ArrayList<>();
        List<String> projectIds = energyDataEntities.stream().map(EnergyDataEntity::getSceneProjectId).collect(Collectors.toList());
        Map<String, SceneProjectEntity> projectEntityMap = projectIds.isEmpty() ? Collections.emptyMap() : sceneProjectService.listByIds(projectIds).stream().collect(Collectors.toMap(SceneProjectEntity::getId, Function.identity()));
        List<String> edificeIds = energyDataEntities.stream().map(EnergyDataEntity::getSceneEdificeId).collect(Collectors.toList());
        Map<String, SceneEdificeEntity> edificeEntityMap = edificeIds.isEmpty() ? Collections.emptyMap() : sceneEdificeService.listByIds(projectIds).stream().collect(Collectors.toMap(SceneEdificeEntity::getId, Function.identity()));
        List<String> floorIds = energyDataEntities.stream().map(EnergyDataEntity::getSceneFloorId).collect(Collectors.toList());
        Map<String, SceneFloorEntity> floorEntityMap = floorIds.isEmpty() ? Collections.emptyMap() : sceneFloorService.listByIds(projectIds).stream().collect(Collectors.toMap(SceneFloorEntity::getId, Function.identity()));
        List<String> roomIds = energyDataEntities.stream().map(EnergyDataEntity::getSceneRoomId).collect(Collectors.toList());
        Map<String, SceneRoomEntity> roomEntityMap = roomIds.isEmpty() ? Collections.emptyMap() : sceneRoomService.listByIds(projectIds).stream().collect(Collectors.toMap(SceneRoomEntity::getId, Function.identity()));
        for (ProductTypeEntity productTypeEntity : productTypeEntities) {
            List<EnergyDataEntity> dataEntities = energyDataEntities.stream()
                    .filter(item -> StringUtils.pathEquals(productTypeEntity.getId(), item.getProductTypeId())).collect(Collectors.toList());
            classificationResps.add(new CarbonEmissionsClassificationResp()
                    .setName(productTypeEntity.getProductTypeName())
                    .setUnit(unit)
                    .setData(dataEntities.stream()
                            .map(item -> new CarbonEmissionsClassificationResp.DataItem()
                                    .setProjectId(item.getSceneProjectId())
                                    .setProjectName(projectEntityMap.containsKey(item.getSceneProjectId()) ? projectEntityMap.get(item.getSceneProjectId()).getProjectName() : null)
                                    .setSceneEdificeId(item.getSceneEdificeId())
                                    .setSceneEdificeName(edificeEntityMap.containsKey(item.getSceneEdificeId()) ? edificeEntityMap.get(item.getSceneEdificeId()).getEdificeName() : null)
                                    .setSceneFloorId(item.getSceneFloorId())
                                    .setSceneFloorName(floorEntityMap.containsKey(item.getSceneFloorId()) ? floorEntityMap.get(item.getSceneFloorId()).getFloorName() : null)
                                    .setSceneRoomId(item.getSceneRoomId())
                                    .setSceneRoomName(roomEntityMap.containsKey(item.getSceneRoomId()) ? roomEntityMap.get(item.getSceneRoomId()).getRoomName() : null)
                                    .setValue(item.getCarbonEmission().setScale(2, RoundingMode.HALF_DOWN)))
                            .collect(Collectors.toList())));
        }
        if (classificationResps.stream().anyMatch(item -> item.getData().stream().anyMatch(dataItem -> dataItem.getValue().compareTo(t) >= 0))) {
            unit = "tCO2";
            for (CarbonEmissionsClassificationResp classificationResp : classificationResps) {
                classificationResp.setUnit(unit);
                for (CarbonEmissionsClassificationResp.DataItem dataItem : classificationResp.getData()) {
                    dataItem.setValue(dataItem.getValue().divide(t, 2, RoundingMode.HALF_DOWN));
                }
            }
        }
        return ResultResp.success(classificationResps);
    }


    /**
     * 能源碳排放统计
     *
     * @param sceneProjectId sceneProjectId
     * @param sceneEdificeId sceneEdificeId
     * @param sceneFloorId   sceneFloorId
     * @param startTime      startTime
     * @param endTime        endTime
     */
    @ApiOperation("能源碳排放统计")
    @GetMapping("energyCarbonEmissionsStatistics")
    public ResultResp<List<EnergyCarbonEmissionsStatisticsResp>> energyCarbonEmissionsStatistics(@RequestParam(required = false) String sceneProjectId,
                                                                                                 @RequestParam(required = false) String sceneEdificeId,
                                                                                                 @RequestParam(required = false) String sceneFloorId,
                                                                                                 @RequestParam(required = false) String startTime,
                                                                                                 @RequestParam(required = false) String endTime) {
        LocalDateTime start = StringUtils.hasLength(startTime) ? LocalDate.parse(startTime, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atTime(LocalTime.MIN) : null;
        LocalDateTime end = StringUtils.hasLength(endTime) ? LocalDate.parse(endTime, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atTime(LocalTime.MAX) : LocalDateTime.now();
        List<EnergyConsumptionTypeEntity> consumptionTypeEntities = energyConsumptionTypeService.list(new LambdaQueryWrapper<EnergyConsumptionTypeEntity>()
                .eq(EnergyConsumptionTypeEntity::getStatus, IMeterDeviceEnums.DelFlag.delFlag1.delFlag)
                .orderByAsc(EnergyConsumptionTypeEntity::getCreateTm));
        String unit = "kgCO2";
        BigDecimal t = new BigDecimal("1000");
        List<EnergyDataEntity> energyDataEntities = Joins.of(EnergyDataEntity.class)
                .selectAs(consumer ->
                        consumer
                                .add("ecp_tt_energy_data.energy_type_id", "energyTypeId", false)
                                .add("SUM(carbon_emission)", "carbonEmission", false)
                )
                .leftJoin(MeterDeviceEntity.class, MeterDeviceEntity::getId, EnergyDataEntity::getMeterDeviceId)
                .notIn(MeterDeviceEntity::getReadMeterType, IMeterDeviceEnums.ReadMeterType.getZeroCarbonList())
                .end()
                .eq(StringUtils.hasLength(sceneProjectId), EnergyDataEntity::getSceneProjectId, sceneProjectId)
                .eq(StringUtils.hasLength(sceneEdificeId), EnergyDataEntity::getSceneEdificeId, sceneEdificeId)
                .eq(StringUtils.hasLength(sceneFloorId), EnergyDataEntity::getSceneFloorId, sceneFloorId)
                .eq(EnergyDataEntity::getEnergyTypeId, energyConsumptionTypeService.getElectricId())
                .ge(Objects.nonNull(start), EnergyDataEntity::getSolidifyDate, start)
                .le(EnergyDataEntity::getSolidifyDate, end)
                .groupBy(EnergyDataEntity::getEnergyTypeId)
                .joinList(EnergyDataEntity.class);
        List<EnergyCarbonEmissionsStatisticsResp> respList = new ArrayList<>();
        List<EnergyCarbonEmissionsStatisticsResp.DataItem> list = consumptionTypeEntities.stream()
                .map(item -> new EnergyCarbonEmissionsStatisticsResp.DataItem()
                        .setName(item.getEnergyName())
                        .setValue(energyDataEntities.stream().filter(energyData -> StringUtils.pathEquals(item.getId(), energyData.getEnergyTypeId()))
                                .map(EnergyDataEntity::getCarbonEmission)
                                .reduce(BigDecimal.ZERO, BigDecimal::add)
                                .setScale(2, RoundingMode.HALF_DOWN)))
                .collect(Collectors.toList());
        respList.add(new EnergyCarbonEmissionsStatisticsResp().setName("市电").setUnit(unit).setData(list));

        List<EnergyDataEntity> energyDataEntities2 = Joins.of(EnergyDataEntity.class)
                .selectAs(consumer ->
                        consumer
                                .add("ecp_tt_energy_data.energy_type_id", "energyTypeId", false)
                                .add("SUM(meter_value)", "meter_value", false)
                )
                .eq(StringUtils.hasLength(sceneProjectId), EnergyDataEntity::getSceneProjectId, sceneProjectId)
                .eq(StringUtils.hasLength(sceneEdificeId), EnergyDataEntity::getSceneEdificeId, sceneEdificeId)
                .eq(StringUtils.hasLength(sceneFloorId), EnergyDataEntity::getSceneFloorId, sceneFloorId)
                .eq(EnergyDataEntity::getReadMeterType, IMeterDeviceEnums.ReadMeterType.readMeterType11.readMeterType)
                .eq(EnergyDataEntity::getStaticsType, MeterDeviceStaticsTypeEnums.POWER_GENERATION.getValue())
                .eq(EnergyDataEntity::getEnergyTypeId, energyConsumptionTypeService.getElectricId())
                .ge(Objects.nonNull(start), EnergyDataEntity::getSolidifyDate, start)
                .le(EnergyDataEntity::getSolidifyDate, end)
                .groupBy(EnergyDataEntity::getEnergyTypeId)
                .joinList(EnergyDataEntity.class);
        List<EnergyDataEntity> energyDataEntities3 = Joins.of(EnergyDataEntity.class)
                .selectAs(consumer ->
                        consumer
                                .add("ecp_tt_energy_data.energy_type_id", "energyTypeId", false)
                                .add("SUM(meter_value)", "meter_value", false)
                )
                .eq(StringUtils.hasLength(sceneProjectId), EnergyDataEntity::getSceneProjectId, sceneProjectId)
                .eq(StringUtils.hasLength(sceneEdificeId), EnergyDataEntity::getSceneEdificeId, sceneEdificeId)
                .eq(StringUtils.hasLength(sceneFloorId), EnergyDataEntity::getSceneFloorId, sceneFloorId)
                .eq(EnergyDataEntity::getReadMeterType, IMeterDeviceEnums.ReadMeterType.readMeterType11.readMeterType)
                .eq(EnergyDataEntity::getStaticsType, MeterDeviceStaticsTypeEnums.ON_GRID_ENERGY.getValue())
                .eq(EnergyDataEntity::getEnergyTypeId, energyConsumptionTypeService.getElectricId())
                .ge(Objects.nonNull(start), EnergyDataEntity::getSolidifyDate, start)
                .le(EnergyDataEntity::getSolidifyDate, end)
                .groupBy(EnergyDataEntity::getEnergyTypeId)
                .joinList(EnergyDataEntity.class);
        respList.add(new EnergyCarbonEmissionsStatisticsResp().setName("光伏发电使用量")
                .setUnit(unit)
                .setData(consumptionTypeEntities.stream()
                        .map(item -> {
                            BigDecimal value = energyDataEntities2.stream().filter(energyDataEntity -> item.getId().equals(energyDataEntity.getEnergyTypeId()))
                                    .findFirst().map(EnergyDataEntity::getMeterValue).orElse(BigDecimal.ZERO);
                            BigDecimal value2 = energyDataEntities3.stream().filter(energyDataEntity -> item.getId().equals(energyDataEntity.getEnergyTypeId()))
                                    .findFirst().map(EnergyDataEntity::getMeterValue).orElse(BigDecimal.ZERO);
                            return new EnergyCarbonEmissionsStatisticsResp.DataItem().setName(item.getEnergyName())
                                    .setValue(value.subtract(value2).setScale(2, RoundingMode.HALF_DOWN));
                        }).collect(Collectors.toList())));

        ActivityCarbonEmissionEntity activityCarbonEmission = activityCarbonEmissionService.findFirstByActivityName("外购绿电");
        List<EnergyCarbonEmissionsStatisticsResp.DataItem> dataList = Collections.emptyList();
        if (Objects.nonNull(activityCarbonEmission)) {
            List<DataFillingDataEntity> dataFillingDataEntities = dataFillingDataService.lambdaQuery()
                    .select(DataFillingDataEntity::getEnergyConsumptionTypeId, DataFillingDataEntity::getCarbonEmission)
                    .eq(DataFillingDataEntity::getActivityCarbonEmissionId, activityCarbonEmission.getId())
                    .eq(StringUtils.hasLength(sceneProjectId), DataFillingDataEntity::getSceneProjectId, sceneProjectId)
                    .eq(StringUtils.hasLength(sceneEdificeId), DataFillingDataEntity::getSceneEdificeId, sceneEdificeId)
                    .eq(StringUtils.hasLength(sceneFloorId), DataFillingDataEntity::getSceneFloorId, sceneFloorId)
                    .ge(Objects.nonNull(start), DataFillingDataEntity::getSolidifyDate, start)
                    .le(DataFillingDataEntity::getSolidifyDate, end).list();
            dataList = consumptionTypeEntities.stream()
                    .map(item -> {
                        BigDecimal value = dataFillingDataEntities.stream()
                                .filter(energyDataEntity -> item.getId().equals(energyDataEntity.getEnergyConsumptionTypeId()))
                                .map(DataFillingDataEntity::getCarbonEmission).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                        return new EnergyCarbonEmissionsStatisticsResp.DataItem().setName(item.getEnergyName())
                                .setValue(value.setScale(2, RoundingMode.HALF_DOWN));
                    }).collect(Collectors.toList());
        }
        respList.add(new EnergyCarbonEmissionsStatisticsResp().setName("外购绿电").setUnit(unit).setData(dataList));
        if (respList.stream().anyMatch(item -> item.getData().stream().anyMatch(itemData -> itemData.getValue().compareTo(t) >= 0))) {
            unit = "tCO2";
            for (EnergyCarbonEmissionsStatisticsResp item : respList) {
                item.setUnit(unit);
                for (EnergyCarbonEmissionsStatisticsResp.DataItem dataItem : item.getData()) {
                    dataItem.setValue(dataItem.getValue().divide(t, 2, RoundingMode.HALF_DOWN));
                }
            }
        }
        return ResultResp.success(respList);
    }

    /**
     * 能源分类统计
     *
     * @param sceneProjectId sceneProjectId
     * @param sceneEdificeId sceneEdificeId
     * @param sceneFloorId   sceneFloorId
     * @param startTime      startTime
     * @param endTime        endTime
     */
    @ApiOperation("能源分类统计")
    @GetMapping("energycategorystatistics")
    public ResultResp<List<EnergyCategoryStatisticsResp>> energyCategoryStatistics(@RequestParam(required = false) String sceneProjectId,
                                                                                   @RequestParam(required = false) String sceneEdificeId,
                                                                                   @RequestParam(required = false) String sceneFloorId,
                                                                                   @RequestParam(required = false) String startTime,
                                                                                   @RequestParam(required = false) String endTime) {
        LocalDateTime start = StringUtils.hasLength(startTime) ? LocalDate.parse(startTime, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atTime(LocalTime.MIN) : null;
        LocalDateTime end = StringUtils.hasLength(endTime) ? LocalDate.parse(endTime, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atTime(LocalTime.MAX) : LocalDateTime.now();
        List<ProductTypeEntity> productTypeEntities = productTypeService.lambdaQuery()
                .eq(ProductTypeEntity::getActiveStatus, ProductTypeActiveStatus.ENABLED.getValue())
                .orderByAsc(ProductTypeEntity::getSort)
                .list();
        List<EnergyCategoryStatisticsResp> list = new ArrayList<>(productTypeEntities.size());
        List<EnergyDataEntity> energyDataEntities = Collections.emptyList();
        if (!productTypeEntities.isEmpty()) {
            energyDataEntities = energyDataService.list(new QueryWrapper<EnergyDataEntity>()
                    .select("product_type_id AS product_type_id", "SUM(standard_coal) AS standardCoal")
                    .isNotNull("product_type_id")
                    .eq(StringUtils.hasLength(sceneProjectId), "scene_project_id", sceneProjectId)
                    .eq(StringUtils.hasLength(sceneEdificeId), "scene_edifice_id", sceneEdificeId)
                    .eq(StringUtils.hasLength(sceneFloorId), "scene_floor_id", sceneFloorId)
                    .ge(Objects.nonNull(start), "solidify_date", start)
                    .le("solidify_date", end)
                    .groupBy("product_type_id")
            );
        }
        String unit = "kgce";
        for (ProductTypeEntity productType : productTypeEntities) {
            EnergyCategoryStatisticsResp statisticsResp = new EnergyCategoryStatisticsResp();
            statisticsResp.setLabel(productType.getProductTypeName());
            statisticsResp.setUnit(unit);
            BigDecimal value = energyDataEntities.stream()
                    .filter(item -> org.apache.commons.lang3.StringUtils.equals(item.getProductTypeId(), productType.getId()))
                    .map(EnergyDataEntity::getStandardCoal)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            statisticsResp.setValue(ObjectUtil.defaultIfNull(value, BigDecimal.ZERO).setScale(2, RoundingMode.HALF_DOWN));
            list.add(statisticsResp);
        }
        BigDecimal t = new BigDecimal("1000");
        if (list.stream().anyMatch(item -> item.getValue().compareTo(t) >= 0)) {
            unit = "tce";
            for (EnergyCategoryStatisticsResp item : list) {
                item.setUnit(unit);
                item.setValue(item.getValue().divide(t, 2, RoundingMode.HALF_UP));
            }
        }
        return ResultResp.success(list);
    }


    /**
     * 能源分项统计
     *
     * @param sceneProjectId projectId
     * @param sceneEdificeId sceneEdificeId
     * @param sceneFloorId   sceneFloorId
     * @param startTime      开始时间
     * @param endTime        结束时间
     */
    @ApiOperation("能源分项统计")
    @GetMapping("energysubstatistics")
    public ResultResp<EnergySubStatisticsResp> energySubStatistics(@RequestParam(required = false) String sceneProjectId,
                                                                   @RequestParam(required = false) String sceneEdificeId,
                                                                   @RequestParam(required = false) String sceneFloorId,
                                                                   @RequestParam(required = false) String startTime,
                                                                   @RequestParam(required = false) String endTime) {
        LocalDateTime start = StringUtils.hasLength(startTime) ? LocalDate.parse(startTime, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atTime(LocalTime.MIN) : null;
        LocalDateTime end = StringUtils.hasLength(endTime) ? LocalDate.parse(endTime, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atTime(LocalTime.MAX) : LocalDateTime.now();
        EnergySubStatisticsResp resp = new EnergySubStatisticsResp();
        String unit = "kgce";
        BigDecimal t = new BigDecimal("1000");
        List<EnergySubStatisticsResp.Detail> details = new ArrayList<>();
        EnergyCategoryEntity primaryEnergy = energyCategoryService.primaryEnergy();
        List<EnergyConsumptionTypeEntity> energyConsumptionTypeEntities = energyConsumptionTypeService.findByEnergyCategoryId(primaryEnergy.getId());
        Set<String> energyTypeIds = energyConsumptionTypeEntities.stream().map(EnergyConsumptionTypeEntity::getId).collect(Collectors.toSet());
        BigDecimal onceEnergy = energyTypeIds.isEmpty() ? BigDecimal.ZERO : staticsEnergyDataOverview(sceneProjectId, sceneEdificeId, sceneFloorId, energyTypeIds, start, end);


        details.add(new EnergySubStatisticsResp.Detail().setName("一次能源").setValue(onceEnergy));

        String electricId = energyConsumptionTypeService.getElectricId();
        List<EnergyDataEntity> energyDataEntities = Joins.of(EnergyDataEntity.class)
                .select(EnergyDataEntity::getCarbonEmission)
                .leftJoin(MeterDeviceEntity.class, MeterDeviceEntity::getId, EnergyDataEntity::getMeterDeviceId)
                .notIn(MeterDeviceEntity::getReadMeterType, IMeterDeviceEnums.ReadMeterType.getZeroCarbonList())
                .end()
                .eq(StringUtils.hasLength(sceneProjectId), EnergyDataEntity::getSceneProjectId, sceneProjectId)
                .eq(StringUtils.hasLength(sceneEdificeId), EnergyDataEntity::getSceneEdificeId, sceneEdificeId)
                .eq(StringUtils.hasLength(sceneFloorId), EnergyDataEntity::getSceneFloorId, sceneFloorId)
                .eq(EnergyDataEntity::getEnergyTypeId, electricId)
                .ge(Objects.nonNull(start), EnergyDataEntity::getSolidifyDate, start)
                .le(EnergyDataEntity::getSolidifyDate, end)
                .orderByAsc(EnergyDataEntity::getSolidifyDate)
                .joinList(EnergyDataEntity.class);
        BigDecimal electricValue = energyDataEntities.stream()
                .map(EnergyDataEntity::getCarbonEmission).filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        details.add(new EnergySubStatisticsResp.Detail().setName("市电").setValue(electricValue));

        DataFillingDataEntity dataEntity = dataFillingDataService.getOne(new QueryWrapper<DataFillingDataEntity>()
                .select("SUM(carbon_emission) carbonEmission")
                .eq(StringUtils.hasLength(sceneProjectId), "scene_project_id", sceneProjectId)
                .eq(StringUtils.hasLength(sceneEdificeId), "scene_edifice_id", sceneEdificeId)
                .eq(StringUtils.hasLength(sceneFloorId), "scene_floor_id", sceneFloorId)
                .gt(Objects.nonNull(start), "solidify_date", start)
                .le("solidify_date", end)
        );
        details.add(new EnergySubStatisticsResp.Detail().setName("光伏发电").setValue(staticsPgTotalEnergyDataOverview(sceneProjectId, sceneEdificeId, sceneFloorId, start, end)));

        BigDecimal totalCarbonEmissionsValue = Objects.isNull(dataEntity) ? BigDecimal.ZERO : ObjectUtil.defaultIfNull(dataEntity.getCarbonEmission(), BigDecimal.ZERO).setScale(2, RoundingMode.HALF_DOWN);
        details.add(new EnergySubStatisticsResp.Detail().setName("外购绿电").setValue(totalCarbonEmissionsValue));

        EnergyCategoryEntity othersEnergy = energyCategoryService.othersEnergy();
        energyConsumptionTypeEntities = energyConsumptionTypeService.findByEnergyCategoryId(othersEnergy.getId());
        energyTypeIds = energyConsumptionTypeEntities.stream().map(EnergyConsumptionTypeEntity::getId).collect(Collectors.toSet());
        BigDecimal otherEnergy = energyTypeIds.isEmpty() ? BigDecimal.ZERO : staticsEnergyDataOverview(sceneProjectId, sceneEdificeId, sceneFloorId, energyTypeIds, start, end);
        details.add(new EnergySubStatisticsResp.Detail().setName("其他").setValue(otherEnergy));
        if (details.stream().anyMatch(item -> item.getValue().compareTo(t) >= 0)) {
            unit = "tce";
            for (EnergySubStatisticsResp.Detail item : details) {
                item.setValue(item.getValue().divide(t, 2, RoundingMode.HALF_UP));
            }
        }
        resp.setData(details);
        resp.setUnit(unit);
        return ResultResp.success(resp);
    }

    private BigDecimal staticsPgTotalEnergyDataOverview(String sceneProjectId,
                                                        String sceneEdificeId,
                                                        String sceneFloorId, LocalDateTime startTime, LocalDateTime endTime) {
        EnergyDataEntity dataEntity = energyDataService.getOne(new QueryWrapper<EnergyDataEntity>()
                .select("SUM(meter_value) AS meter_value")
                .eq(StringUtils.hasLength(sceneProjectId), "scene_project_id", sceneProjectId)
                .eq(StringUtils.hasLength(sceneEdificeId), "scene_edifice_id", sceneEdificeId)
                .eq(StringUtils.hasLength(sceneFloorId), "scene_floor_id", sceneFloorId)
                .eq("read_meter_type", IMeterDeviceEnums.ReadMeterType.readMeterType11.readMeterType)
                .eq("statics_type", MeterDeviceStaticsTypeEnums.POWER_GENERATION.getValue())
                .ge(Objects.nonNull(startTime), "solidify_date", startTime)
                .le(Objects.nonNull(endTime), "solidify_date", endTime));
        return Objects.isNull(dataEntity) ? BigDecimal.ZERO : ObjectUtil.defaultIfNull(dataEntity.getMeterValue(), BigDecimal.ZERO)
                .setScale(2, RoundingMode.HALF_DOWN);
    }

    private BigDecimal staticsEnergyDataOverview(String sceneProjectId,
                                                 String sceneEdificeId,
                                                 String sceneFloorId,Set<String> energyTypeIds,  LocalDateTime startTime, LocalDateTime endTime) {
        EnergyDataEntity dataEntity = energyDataService.getOne(new QueryWrapper<EnergyDataEntity>()
                .select("SUM(standard_coal) AS standard_coal")
                .eq(StringUtils.hasLength(sceneProjectId), "scene_project_id", sceneProjectId)
                .eq(StringUtils.hasLength(sceneEdificeId), "scene_edifice_id", sceneEdificeId)
                .eq(StringUtils.hasLength(sceneFloorId), "scene_floor_id", sceneFloorId)
                .in(!CollectionUtils.isEmpty(energyTypeIds), "energy_type_id", energyTypeIds)
                .ge(Objects.nonNull(startTime), "solidify_date", startTime)
                .le(Objects.nonNull(endTime), "solidify_date", endTime));
        return Objects.isNull(dataEntity) ? BigDecimal.ZERO : ObjectUtil.defaultIfNull(dataEntity.getStandardCoal(), BigDecimal.ZERO)
                .setScale(2, RoundingMode.HALF_DOWN);
    }

    private MiniDeviceInfoCategoryResp.DeviceInfoCategory setDeviceInfoCategory(MiniDeviceInfoCategoryResp.DeviceInfoCategory deviceInfoCategory,
                                                                                List<Map<String, Object>> devices, String productTypeId) {
        Object onlineCount = devices.stream()
                .filter(item -> Objects.equals(item.get("product_type_id"), productTypeId) && "1".equals(item.get("device_status")))
                .map(item -> item.get("count_value"))
                .findFirst()
                .orElse(null);
        int online = Objects.isNull(onlineCount) ? 0 : Integer.parseInt(onlineCount.toString());
        Object offlineCount = devices.stream()
                .filter(item -> Objects.equals(item.get("product_type_id"), productTypeId) && "2".equals(item.get("device_status")))
                .map(item -> item.get("count_value"))
                .findFirst()
                .orElse(null);
        int offline = Objects.isNull(offlineCount) ? 0 : Integer.parseInt(offlineCount.toString());
        return deviceInfoCategory.setOnLineDevicesNum(online)
                .setOutLineDevicesNum(offline);
    }

    private List<Map<String, Object>> deviceByCategory(Set<String> productTypeIds, String sceneProjectId,
                                                       String sceneEdificeId,
                                                       String sceneFloorId) {
        return deviceService.listMaps(new QueryWrapper<DeviceEntity>()
                .select("product_type_id", "device_status", "count(id) as count_value")
                .eq("device_type", IDeviceEnums.DeviceType.deviceType1.getValue())
                .eq(StringUtils.hasLength(sceneProjectId), "scene_project_id", sceneProjectId)
                .eq(StringUtils.hasLength(sceneEdificeId), "scene_edifice_id", sceneEdificeId)
                .eq(StringUtils.hasLength(sceneFloorId), "scene_floor_id", sceneFloorId)
                .in("product_type_id", productTypeIds)
                .isNotNull("device_status")
                .groupBy("product_type_id", "device_status")
        );
    }

    private List<Map<String, Object>> meterDevice(String sceneProjectId,
                                                  String sceneEdificeId,
                                                  String sceneFloorId) {
        return meterDeviceService.listMaps(new QueryWrapper<MeterDeviceEntity>()
                .select("product_type_id", "device_status", "count(id) as count_value")
                .eq(StringUtils.hasLength(sceneProjectId), "scene_project_id", sceneProjectId)
                .eq(StringUtils.hasLength(sceneEdificeId), "scene_edifice_id", sceneEdificeId)
                .eq(StringUtils.hasLength(sceneFloorId), "scene_floor_id", sceneFloorId)
                .eq("del_flag", IMeterDeviceEnums.DelFlag.delFlag1.delFlag)
                .isNotNull("device_status")
                .groupBy("product_type_id", "device_status"));
    }
}
